package com.daqian.mall.utils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.daqian.mall.entity.BaseCategory;
import com.daqian.mall.mapper.BaseCategoryMapper;
import com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.DefaultResponseErrorHandler;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 通过多线程获取旺铺类目
 *
 * @Author: daqian
 * @Date: 2018/4/4 16:49
 */
public class CustomThreadPoolExecutor {
    /*
    一、通过js获取一级分类信息
    1.进入http://www.weimob.com/vshop/index/373549
    2.在页面console通过执行下面JS，来获取一级分类id列表（用于获取子类列表）和sql语句（用于向数据库插入一级分类）
        var lis = document.getElementsByClassName("category_items")[0].getElementsByTagName("li");
        var wids = "";
        for (var i = 0; i < lis.length; i++) {
            var li = lis[i];
            var wid = li.getAttribute("wid");
            var title = li.getElementsByTagName("a")[0].getAttribute("title");
            wids += wid + ','

            var sql = "insert into category (id, val, pid, lv) values ('" + wid + "','" + title + "', 0, 0);";
            console.log(sql);
        }
        console.log(wids);
    */

    /*
    二、通过一级分类信息，用下方java代码获取所有子类列表
     */


    /**
     * 通过父类id查询子类集合
     */
    private static String url_get_category = "http://www.weimob.com/vshop/Ajax/Get/GetCategoryByParentId/%s?_=1522820267425";
    /**
     * 通过父类id查询子类集合
     */
    private static String url_get_attr = "http://www.weimob.com/vshop/Ajax/Get/AttributeByCategory/%s?_=1523153039903";
    /**
     * 通过父类id查询子类集合
     */
    private static String url_get_spec = "http://www.weimob.com/vshop/Ajax/Get/SKUByCategory/%s?_=1523153039907";

    /**
     * 旺铺后台登录后的cookie
     */
    private static String cookie = "js_design_tips=true; __DAYU_PP=NuNIqYr2jrQiRFQFIy7V2cd37be6a002; rprm_cuid=MTUxNTU3Njg0MjYy; _jzqa=1.354617996865980800.1515576846.1515576846.1515576846.1; _qzja=1.1613346975.1515576845738.1515576845739.1522398429851.1522398458890.1522398461277.0.0.0.11.2; _qzjc=1; weimobSID=7c5jrmtsqqrnth2cmsjdtfo6t7; saasAuthData=967ff56bfd94fea92f124334d48db0b1; weimobAuthData=762e2d1844b2fddd52e0ae5f1ca75233; authDataType=weimob; __hash__site=YToxMzp7czo2OiJ1c2VyaWQiO2k6NTkzMzk7czo4OiJ1c2VydHlwZSI7aTozO3M6ODoidXNlcm5hbWUiO3M6MTI6IndlaW1vYi16YzAwOSI7czo0OiJuYW1lIjtzOjE4OiLlvq7nm5%2FmioDmnK%2FmlK%2FmjIEiO3M6OToia2VlcGFsaXZlIjtpOjA7czo4OiJwYXNzd29yZCI7czozMjoiODRlMjBkOWZmM2I5NTg4MjA5NjhkOTMwY2NmZGU1YzQiO3M6MTI6Im5ld19wYXNzd29yZCI7czozMjoiY2M1NGY2ZDU3M2U4ZTBiMTg4Y2FkY2RiNWZmZWFhZjYiO3M6MjI6ImlzX2NoYW5nZV9uZXdfcGFzc3dvcmQiO3M6MToiMSI7czoxNDoiaXNfY2hhbmdlX2ZsYWciO3M6MToiMiI7czoxODoiTkVFRF9SRUZSRVNIX01FTlVTIjtOO3M6MTA6InNlcnZpY2VfaWQiO3M6MToiMyI7czo1OiJldGltZSI7czoxMDoiMTU3Nzc4MjY4MCI7czozOiJlbnYiO3M6NjoiT05MSU5FIjt9; wsession_id=7c5jrmtsqqrnth2cmsjdtfo6t7; ASP.NET_SessionId=zjraxhc1y20uuomvuoa2eivs; Hm_lvt_d80741dd59de91e1846b2add2c0ad2a2=1522398809; Hm_lpvt_d80741dd59de91e1846b2add2c0ad2a2=1522403301; express.session=s%3ArqA9AuTeu8SpCQ0dLORf8fOOwIX-LbO4.TLYEooqWeJRCrbN1CmaURrZFtzP%2B7Ic3bghA%2Bb5Gy%2BU; rprm_mjcinfo=NA; rprm_csource=baiducpc-weimeng; Hm_lvt_c1df8c79ab44a42f4e36f5ae9b1f6d48=1522398430; Hm_lpvt_c1df8c79ab44a42f4e36f5ae9b1f6d48=1522648995; pc_aid=pc_373549; __hash__=YToxMzp7czo2OiJ1c2VyaWQiO2k6NTkzMzk7czo4OiJ1c2VydHlwZSI7aTozO3M6ODoidXNlcm5hbWUiO3M6MTI6IndlaW1vYi16YzAwOSI7czo0OiJuYW1lIjtzOjE4OiLlvq7nm5%2FmioDmnK%2FmlK%2FmjIEiO3M6OToia2VlcGFsaXZlIjtpOjA7czo4OiJwYXNzd29yZCI7czozMjoiODRlMjBkOWZmM2I5NTg4MjA5NjhkOTMwY2NmZGU1YzQiO3M6MTI6Im5ld19wYXNzd29yZCI7czozMjoiY2M1NGY2ZDU3M2U4ZTBiMTg4Y2FkY2RiNWZmZWFhZjYiO3M6MjI6ImlzX2NoYW5nZV9uZXdfcGFzc3dvcmQiO3M6MToiMSI7czoxNDoiaXNfY2hhbmdlX2ZsYWciO3M6MToiMiI7czoxODoiTkVFRF9SRUZSRVNIX01FTlVTIjtOO3M6MTA6InNlcnZpY2VfaWQiO3M6MToiMyI7czo1OiJldGltZSI7czoxMDoiMTU3Nzc4MjY4MCI7czozOiJlbnYiO3M6NjoiT05MSU5FIjt9; __verify__=3649dc714fefbddeb9b81379d204deaf; VshopLogin=eyJBSWQiOjM3MzU0OSwiUGVybWlzc2lvbnMiOiIiLCJVc2VyVHlwZSI6MywiQ2lwaGVyIjoiN2M5OGJlYmIyOWUyZmU1OWI4ZjhjODUwYTJkYTBmM2EiLCJIYXNoVXNlcktleSI6IllUb3hNenA3Y3pvMk9pSjFjMlZ5YVdRaU8yazZOVGt6TXprN2N6bzRPaUoxYzJWeWRIbHdaU0k3YVRvek8zTTZPRG9pZFhObGNtNWhiV1VpTzNNNk1USTZJbmRsYVcxdllpMTZZekF3T1NJN2N6bzBPaUp1WVcxbElqdHpPakU0T2lMbHZxN25tNSUyRm1pb0RtbkslMkZtbEslMkZtaklFaU8zTTZPVG9pYTJWbGNHRnNhWFpsSWp0cE9qQTdjem80T2lKd1lYTnpkMjl5WkNJN2N6b3pNam9pT0RSbE1qQmtPV1ptTTJJNU5UZzRNakE1Tmpoa09UTXdZMk5tWkdVMVl6UWlPM002TVRJNkltNWxkMTl3WVhOemQyOXlaQ0k3Y3pvek1qb2lZMk0xTkdZMlpEVTNNMlU0WlRCaU1UZzRZMkZrWTJSaU5XWm1aV0ZoWmpZaU8zTTZNakk2SW1selgyTm9ZVzVuWlY5dVpYZGZjR0Z6YzNkdmNtUWlPM002TVRvaU1TSTdjem94TkRvaWFYTmZZMmhoYm1kbFgyWnNZV2NpTzNNNk1Ub2lNaUk3Y3pveE9Eb2lUa1ZGUkY5U1JVWlNSVk5JWDAxRlRsVlRJanRPTzNNNk1UQTZJbk5sY25acFkyVmZhV1FpTzNNNk1Ub2lNeUk3Y3pvMU9pSmxkR2x0WlNJN2N6b3hNRG9pTVRVM056YzRNalk0TUNJN2N6b3pPaUpsYm5ZaU8zTTZOam9pVDA1TVNVNUZJanQ5IiwiSm9iTnVtYmVyIjoid2VpbW9iLXpjMDA5IiwiSm9iTmFtZSI6IjViNnU1NXVmNW9xQTVweXY1cFN2NW95QiIsIlVzZXJJZCI6NTkzMzksIlBvd2VySWQiOjB9";


    public static void main(String[] args) {
        //打印类目信息
        //new CustomThreadPoolExecutor().printCategory();
    }

    /**
     * 多线程同步类目信息
     */
    public void syncCategory() {
        CustomThreadPoolExecutor exec = new CustomThreadPoolExecutor();
        // 1.初始化
        exec.init();
        ExecutorService pool = exec.getCustomThreadPoolExecutor();
        //一级分类id列表
        String wids = "538070935,538072052,538101922,537892413,537898958,538112995,538112192,538112937,538112978" +
                ",538096864,538100515,537870913,538096552,537895413,538111060,538372728,537876982,537906649,537898966" +
                ",538112993,537898965,537898967,537898968,537892913,538370913,538372764,538372688,538112979,537890913" +
                ",538104511,537905079,538112994,537898070,537891913,537891948,537072692,538371746,537879913,537876913" +
                ",538082593,538372738,538071212,537891413,537872913,537894413,537898921,537874913,537893413,537898951" +
                ",538113282,538088633,538372669,538372786,537894913,538104253,537878913,538103269,538104513,537905439" +
                ",537876929,538104512,537903127,537880913,560880001,537074893";
        String[] widsArr = wids.split(",");
        for (int i = 0; i < widsArr.length; i++) {
            String wid = widsArr[i];
            System.out.println("提交第" + i + "个任务!");
            //pool.execute(() -> {
            ResponseEntity<String> result = httpGet(String.format(url_get_category, wid));
            //子分类列表，示例：[{"key":"538071219","val":"饼干/糕点/膨化食品"},{"key":"538071218","val":"茶叶/普洱/花草茶"}]
            JSONArray subClass = JSONArray.parseArray(result.getBody());
            printData(wid, "", subClass, 0);
            //});
        }
    }

    public ExecutorService getCustomThreadPoolExecutor() {
        return this.pool;
    }

    private ThreadPoolExecutor pool = null;

    /**
     * 线程池初始化方法
     * <p>
     * corePoolSize 核心线程池大小----20
     * maximumPoolSize 最大线程池大小----70
     * keepAliveTime 线程池中超过corePoolSize数目的空闲线程最大存活时间----30+单位TimeUnit
     * TimeUnit keepAliveTime时间单位----TimeUnit.MINUTES
     * workQueue 阻塞队列----new ArrayBlockingQueue<Runnable>(10)====10容量的阻塞队列
     * threadFactory 新建线程工厂----new CustomThreadFactory()====定制的线程工厂
     * rejectedExecutionHandler 当提交任务数超过maxmumPoolSize+workQueue之和时,
     * 即当提交第41个任务时(前面线程都没有执行完,此测试方法中用sleep(100)),
     * 任务会交给RejectedExecutionHandler来处理
     */
    public void init() {
        pool = new ThreadPoolExecutor(
                20,
                70,
                30,
                TimeUnit.MINUTES,
                new ArrayBlockingQueue<Runnable>(10),
                new CustomThreadFactory(),
                new CustomRejectedExecutionHandler());
    }

    private class CustomThreadFactory implements ThreadFactory {
        private AtomicInteger count = new AtomicInteger(0);

        @Override
        public Thread newThread(Runnable r) {
            Thread t = new Thread(r);
            String threadName = CustomThreadPoolExecutor.class.getSimpleName() + count.addAndGet(1);
            System.out.println(threadName);
            t.setName(threadName);
            return t;
        }
    }


    private class CustomRejectedExecutionHandler implements RejectedExecutionHandler {
        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
            // 记录异常
            // 报警处理等
            System.out.println("error.............");
        }
    }

    @Resource
    private BaseCategoryMapper baseCategoryMapper;

    public List<BaseCategory> printCategoryOne() {
        return baseCategoryMapper.selectAll();
    }

    /**
     * 打印数据
     *
     * @param pkey
     * @param pval
     * @param subClass
     * @param lastLevel
     */
    public void printData(String pkey, String pval, JSONArray subClass, int lastLevel) {
        if (subClass != null && subClass.size() > 0) {
            System.out.println("--" + pkey + ":" + pval + lastLevel + "|开始=输出" + subClass.size());
            for (int i = 0; i < subClass.size(); i++) {
                JSONObject j = subClass.getJSONObject(i);
                String key = j.getString("key");
                String val = j.getString("val");

                String attr = httpGet(String.format(url_get_attr, key)).getBody().replaceAll("'", "`").replaceAll("\t", "");
                String spec = httpGet(String.format(url_get_spec, key)).getBody().replaceAll("'", "`").replaceAll("\t", "");
                //输出当前分类
                //System.out.println("insert into category (id, val, pid, lv, attr_list, spec_list) values ('" + key + "','" + val + "','" + pkey + "'," + (lastLevel + 1) + ",'" + attr + ",'" + spec + "');");
                //保存类目
                BaseCategory c = new BaseCategory();
                c.setId(Long.parseLong(key));
                c.setVal(val);
                c.setPid(Long.parseLong(pkey));
                c.setLv(lastLevel + 1);
                c.setAttrList(JSONObject.parseObject(attr).getJSONArray("data").toJSONString());
                c.setSpecList(JSONObject.parseObject(spec).getJSONArray("data").toJSONString());
                try {
                    baseCategoryMapper.insert(c);
                } catch (Exception e) {
                    if (e instanceof MySQLIntegrityConstraintViolationException) {
                        //System.out.println("插入失败-主键重复");
                    } else {
                        System.out.println("插入失败：" + e.getMessage());
                        e.printStackTrace();
                    }
                }

                //类目
                ResponseEntity<String> category = httpGet(String.format(url_get_category, key));
                //子分类列表，示例：[{"key":"538071219","val":"饼干/糕点/膨化食品"},{"key":"538071218","val":"茶叶/普洱/花草茶"}]
                JSONArray subClass2 = JSONArray.parseArray(category.getBody());
                printData(key, val, subClass2, lastLevel + 1);
            }
        } else {
            System.out.println("--" + pkey + ":" + pval + lastLevel + "|没有子分类了");
        }
    }

    /**
     * http get请求工具
     *
     * @param url
     * @return
     */
    public static ResponseEntity<String> httpGet(String url) {
        //请求头
        HttpHeaders headers = new HttpHeaders();
        List<String> cookieList = new ArrayList<>();
        cookieList.add(cookie);
        headers.put(HttpHeaders.COOKIE, cookieList);
        //请求体
        HttpEntity<String> request = new HttpEntity<>(headers);
        RestTemplate restTemplate = new RestTemplate();
        restTemplate.setErrorHandler(new DefaultResponseErrorHandler());
        ResponseEntity<String> result = restTemplate.exchange(url, HttpMethod.GET, request, String.class);
        return result;
    }

}
